package com.citic.topview.system.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.citic.topview.common.system.entity.User;
import com.citic.topview.common.system.entity.UserRole;
import com.citic.topview.common.system.vo.UserVO;
import com.citic.topview.common.util.EncodesUtil;
import com.citic.topview.common.util.IdGen;
import com.citic.topview.system.dao.UserDao;
import com.citic.topview.system.dao.UserRoleDao;
import com.citic.topview.system.persistence.CrudService;
import com.citic.topview.system.security.UserRealm;
import com.citic.topview.system.security.manager.Digests;
import com.citic.topview.system.util.CollectionUtils;
import com.citic.topview.system.util.ShiroUtils;

@Service
@Transactional(readOnly = true)
public class UserService extends CrudService<UserDao, User>{

	@Autowired
	UserRoleDao userRoleDao;
	
	public User get(Long id) {
		return super.get(id);
	}

	@Transactional(readOnly = false)
	public int save(User user) {
		return super.save(user);
	}

	@Transactional(readOnly = false)
	public int save(User user, Long[] roleIds) {
		super.save(user);
		
		List<UserRole> list = new ArrayList<>();
		UserRole userRole = null;
		for (Long roleId : roleIds) {
			if(roleId > 0L) {
				userRole = new UserRole();
				userRole.setId(IdGen.snowFlakeId());
				userRole.setRoleId(roleId);
				userRole.setUserId(user.getId());
				list.add(userRole);
			}
		}
		
		userRoleDao.removeByUserId(user.getId());
		if(list.size() > 0) {
			return userRoleDao.batchSave(list);
		}
		
		return 1;
	}
	
	@Transactional(readOnly = false)
	public int update(User user) {
		return super.update(user);
	}

	@Transactional(readOnly = false)
	public int update(User user, Long[] roleIds, UserRealm userRealm) {
		super.update(user);
		
		List<UserRole> list = new ArrayList<>();
		UserRole userRole = null;
		for (Long roleId : roleIds) {
			if(roleId > 0L) {
				userRole = new UserRole();
				userRole.setId(IdGen.snowFlakeId());
				userRole.setRoleId(roleId);
				userRole.setUserId(user.getId());
				list.add(userRole);
			}
		}
		
		userRoleDao.removeByUserId(user.getId());
		if(list.size() > 0) {
			List<Long> ids1 = userRoleDao.listRoleId(user.getId());
			List<Long> ids2 = Arrays.asList(roleIds);
			if(CollectionUtils.isEqual(ids1, ids2)) {
				userRealm.clearAuthz();
			}
			return userRoleDao.batchSave(list);
		}
		
		return 0;
	}
	
	@Transactional(readOnly = false)
	public int remove(Long id) {
		return super.remove(id);
	}

	@Transactional(readOnly = false)
	public int deleteByDelFlag(Long id) {
		return super.deleteByDelFlag(id);
	}

	@Transactional(readOnly = false)
	public int batchRemove(Long[] ids) {
		return super.batchRemove(ids);
	}
	
	public List<UserVO> list(Map<String, Object> params) {
		return dao.list(params);
	}
	
	public List<UserVO> listQuery(Map<String, Object> params) {
		return dao.listQuery(params);
	}
	
	public String listByIN(String[] ids) {
		Long[] ls = new Long[ids.length];
		for (int i = 0; i < ids.length; i++) {
			ls[i] = Long.valueOf(ids[i]);
		}
		
		List<UserVO> list = dao.listByIN(ls);
		StringBuffer buffer = new StringBuffer(StringUtils.EMPTY);
		for (UserVO userVO : list) {
			buffer.append(userVO.getName()).append(",");
		}
		
		return buffer.toString();
	}
	
	public int count(Map<String, Object> params) {
		return dao.count(params);
	}
	
	public User getByUser(Map<String, Object> params) {
		return dao.getByUser(params);
	}

	@Transactional(readOnly = false)
	public String updatePassword(UserVO userVO) {
		User user = ShiroUtils.getUser();
		byte[] salt = EncodesUtil.decodeHex(user.getPassword().substring(0, 16));  
		String password = user.getPassword().substring(16);
		
		String tokenCredentials = userVO.getPassword();
		byte[] tokenHashPassword = Digests.sha1(tokenCredentials.getBytes(), salt, SystemService.HASH_INTERATIONS);
		tokenCredentials = EncodesUtil.encodeHex(tokenHashPassword);
		
		if(!password.equals(tokenCredentials)) {
			return "旧密码不正确";
		}
		
		user.setPassword(SystemService.entryptPassword(userVO.getNewPassword()));		
		update(user);
		return "更新密码成功";
	}
}
